home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows (5th Edition) / Programming Windows, 5th ed. - Companion CD (097-0002183)(1999).iso / Chap15 / SeqDisp / SeqDisp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-09  |  10.9 KB  |  309 lines

  1. /*-----------------------------------------
  2.    SEQDISP.C -- Sequential Display of DIBs
  3.                 (c) Charles Petzold, 1998
  4.   -----------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include "resource.h"
  8.  
  9. LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
  10.  
  11. TCHAR szAppName[] = TEXT ("SeqDisp") ;
  12.  
  13. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  14.                     PSTR szCmdLine, int iCmdShow)
  15. {
  16.      HACCEL   hAccel ;
  17.      HWND     hwnd ;
  18.      MSG      msg ;
  19.      WNDCLASS wndclass ;
  20.  
  21.      wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  22.      wndclass.lpfnWndProc   = WndProc ;
  23.      wndclass.cbClsExtra    = 0 ;
  24.      wndclass.cbWndExtra    = 0 ;
  25.      wndclass.hInstance     = hInstance ;
  26.      wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  27.      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  28.      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  29.      wndclass.lpszMenuName  = szAppName ;
  30.      wndclass.lpszClassName = szAppName ;
  31.  
  32.      if (!RegisterClass (&wndclass))
  33.      {
  34.           MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
  35.                       szAppName, MB_ICONERROR) ;
  36.           return 0 ;
  37.      }
  38.      
  39.      hwnd = CreateWindow (szAppName, TEXT ("DIB Sequential Display"),
  40.                           WS_OVERLAPPEDWINDOW,
  41.                           CW_USEDEFAULT, CW_USEDEFAULT,
  42.                           CW_USEDEFAULT, CW_USEDEFAULT, 
  43.                           NULL, NULL, hInstance, NULL) ;
  44.      
  45.      ShowWindow (hwnd, iCmdShow) ;
  46.      UpdateWindow (hwnd) ;
  47.  
  48.      hAccel = LoadAccelerators (hInstance, szAppName) ;
  49.      
  50.      while (GetMessage (&msg, NULL, 0, 0))
  51.      {
  52.           if (!TranslateAccelerator (hwnd, hAccel, &msg))
  53.           {
  54.                TranslateMessage (&msg) ;
  55.                DispatchMessage (&msg) ;
  56.           }
  57.      }
  58.      return msg.wParam ;
  59. }
  60.  
  61. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  62. {
  63.      static BITMAPINFO * pbmi ;
  64.      static BYTE       * pBits ;
  65.      static int          cxDib, cyDib, cBits ;
  66.      static OPENFILENAME ofn ;
  67.      static TCHAR        szFileName [MAX_PATH], szTitleName [MAX_PATH] ;
  68.      static TCHAR        szFilter[] = TEXT ("Bitmap Files (*.BMP)\0*.bmp\0")
  69.                                       TEXT ("All Files (*.*)\0*.*\0\0") ;
  70.      BITMAPFILEHEADER    bmfh ;
  71.      BOOL                bSuccess, bTopDown ;
  72.      DWORD               dwBytesRead ;
  73.      HANDLE              hFile ;
  74.      HDC                 hdc ;
  75.      HMENU               hMenu ;
  76.      int                 iInfoSize, iBitsSize, iRowLength, y ;
  77.      PAINTSTRUCT         ps ;
  78.      
  79.      switch (message)
  80.      {
  81.      case WM_CREATE:
  82.           ofn.lStructSize       = sizeof (OPENFILENAME) ;
  83.           ofn.hwndOwner         = hwnd ;
  84.           ofn.hInstance         = NULL ;
  85.           ofn.lpstrFilter       = szFilter ;
  86.           ofn.lpstrCustomFilter = NULL ;
  87.           ofn.nMaxCustFilter    = 0 ;
  88.           ofn.nFilterIndex      = 0 ;
  89.           ofn.lpstrFile         = szFileName ;
  90.           ofn.nMaxFile          = MAX_PATH ;
  91.           ofn.lpstrFileTitle    = szTitleName ;
  92.           ofn.nMaxFileTitle     = MAX_PATH ;
  93.           ofn.lpstrInitialDir   = NULL ;
  94.           ofn.lpstrTitle        = NULL ;
  95.           ofn.Flags             = 0 ;
  96.           ofn.nFileOffset       = 0 ;
  97.           ofn.nFileExtension    = 0 ;
  98.           ofn.lpstrDefExt       = TEXT ("bmp") ;
  99.           ofn.lCustData         = 0 ;
  100.           ofn.lpfnHook          = NULL ;
  101.           ofn.lpTemplateName    = NULL ;
  102.           return 0 ;
  103.  
  104.      case WM_COMMAND:
  105.           hMenu = GetMenu (hwnd) ; 
  106.  
  107.           switch (LOWORD (wParam))
  108.           {
  109.           case IDM_FILE_OPEN:
  110.                     // Display File Open dialog
  111.  
  112.                if (!GetOpenFileName (&ofn))
  113.                     return 0 ;
  114.  
  115.                     // Get rid of old DIB
  116.  
  117.                if (pbmi)
  118.                {
  119.                     free (pbmi) ;
  120.                     pbmi = NULL ;
  121.                }
  122.  
  123.                if (pBits)
  124.                {
  125.                     free (pBits) ;
  126.                     pBits = NULL ;
  127.                }
  128.  
  129.                     // Generate WM_PAINT message to erase background
  130.  
  131.                InvalidateRect (hwnd, NULL, TRUE) ;
  132.                UpdateWindow (hwnd) ;
  133.  
  134.                     // Open the file
  135.  
  136.                hFile = CreateFile (szFileName, GENERIC_READ, 
  137.                                    FILE_SHARE_READ, NULL, OPEN_EXISTING, 
  138.                                    FILE_FLAG_SEQUENTIAL_SCAN, NULL) ;
  139.  
  140.                if (hFile == INVALID_HANDLE_VALUE)
  141.                {
  142.                     MessageBox (hwnd, TEXT ("Cannot open file."), 
  143.                                 szAppName, MB_ICONWARNING | MB_OK) ;
  144.                     return 0 ;
  145.                }
  146.  
  147.                     // Read in the BITMAPFILEHEADER
  148.  
  149.                bSuccess = ReadFile (hFile, &bmfh, sizeof (BITMAPFILEHEADER),
  150.                                     &dwBytesRead, NULL) ;
  151.  
  152.                if (!bSuccess || dwBytesRead != sizeof (BITMAPFILEHEADER))
  153.                {
  154.                     MessageBox (hwnd, TEXT ("Cannot read file."), 
  155.                                 szAppName, MB_ICONWARNING | MB_OK) ;
  156.                     CloseHandle (hFile) ;
  157.                     return 0 ;
  158.                }
  159.  
  160.                     // Check that it's a bitmap
  161.  
  162.                if (bmfh.bfType != * (WORD *) "BM")
  163.                {
  164.                     MessageBox (hwnd, TEXT ("File is not a bitmap."), 
  165.                                 szAppName, MB_ICONWARNING | MB_OK) ;
  166.                     CloseHandle (hFile) ;
  167.                     return 0 ;
  168.                }
  169.  
  170.                     // Allocate memory for header and bits
  171.  
  172.                iInfoSize = bmfh.bfOffBits - sizeof (BITMAPFILEHEADER) ;
  173.                iBitsSize = bmfh.bfSize - bmfh.bfOffBits ;
  174.  
  175.                pbmi  = malloc (iInfoSize) ;
  176.                pBits = malloc (iBitsSize) ;
  177.  
  178.                if (pbmi == NULL || pBits == NULL)
  179.                {
  180.                     MessageBox (hwnd, TEXT ("Cannot allocate memory."), 
  181.                                 szAppName, MB_ICONWARNING | MB_OK) ;
  182.                     if (pbmi) 
  183.                          free (pbmi) ;
  184.                     if (pBits) 
  185.                          free (pBits) ;
  186.                     CloseHandle (hFile) ;
  187.                     return 0 ;
  188.                }
  189.  
  190.                     // Read in the Information Header
  191.  
  192.                bSuccess = ReadFile (hFile, pbmi, iInfoSize,
  193.                                     &dwBytesRead, NULL) ;
  194.  
  195.                if (!bSuccess || (int) dwBytesRead != iInfoSize)
  196.                {
  197.                     MessageBox (hwnd, TEXT ("Cannot read file."), 
  198.                                 szAppName, MB_ICONWARNING | MB_OK) ;
  199.                     if (pbmi) 
  200.                          free (pbmi) ;
  201.                     if (pBits) 
  202.                          free (pBits) ;
  203.                     CloseHandle (hFile) ;
  204.                     return 0 ;
  205.                }
  206.  
  207.                     // Get the DIB width and height
  208.  
  209.                bTopDown = FALSE ;
  210.  
  211.                if (pbmi->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
  212.                {
  213.                     cxDib = ((BITMAPCOREHEADER *) pbmi)->bcWidth ;
  214.                     cyDib = ((BITMAPCOREHEADER *) pbmi)->bcHeight ;
  215.                     cBits = ((BITMAPCOREHEADER *) pbmi)->bcBitCount ;
  216.                }
  217.                else
  218.                {
  219.                     if (pbmi->bmiHeader.biHeight < 0)
  220.                          bTopDown = TRUE ;
  221.  
  222.                     cxDib =      pbmi->bmiHeader.biWidth ;
  223.                     cyDib = abs (pbmi->bmiHeader.biHeight) ;
  224.                     cBits =      pbmi->bmiHeader.biBitCount ;
  225.  
  226.                     if (pbmi->bmiHeader.biCompression != BI_RGB &&
  227.                         pbmi->bmiHeader.biCompression != BI_BITFIELDS)
  228.                     {
  229.                          MessageBox (hwnd, TEXT ("File is compressed."), 
  230.                                      szAppName, MB_ICONWARNING | MB_OK) ;
  231.                          if (pbmi) 
  232.                               free (pbmi) ;
  233.                          if (pBits) 
  234.                               free (pBits) ;
  235.                          CloseHandle (hFile) ;
  236.                          return 0 ;
  237.                     }
  238.                }
  239.    
  240.                     // Get the row length
  241.  
  242.                iRowLength = ((cxDib * cBits + 31) & ~31) >> 3 ;
  243.  
  244.                     // Read and display
  245.  
  246.                SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
  247.                ShowCursor (TRUE) ;
  248.  
  249.                hdc = GetDC (hwnd) ;
  250.  
  251.                for (y = 0 ; y < cyDib ; y++)
  252.                {
  253.                     ReadFile (hFile, pBits + y * iRowLength, iRowLength,
  254.                               &dwBytesRead, NULL) ;
  255.  
  256.                     SetDIBitsToDevice (hdc, 
  257.                                        0,         // xDst
  258.                                        0,         // yDst
  259.                                        cxDib,     // cxSrc
  260.                                        cyDib,     // cySrc
  261.                                        0,         // xSrc
  262.                                        0,         // ySrc
  263.                                        bTopDown ? cyDib - y - 1 : y,
  264.                                                   // first scan line
  265.                                        1,         // number of scan lines
  266.                                        pBits + y * iRowLength, 
  267.                                        pbmi, 
  268.                                        DIB_RGB_COLORS) ;
  269.                }
  270.                ReleaseDC (hwnd, hdc) ;
  271.                CloseHandle (hFile) ;
  272.                ShowCursor (FALSE) ;
  273.                SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
  274.                return 0 ;
  275.           }
  276.           break ;
  277.  
  278.      case WM_PAINT:
  279.           hdc = BeginPaint (hwnd, &ps) ;
  280.  
  281.           if (pbmi && pBits)
  282.                SetDIBitsToDevice (hdc, 
  283.                                   0,         // xDst
  284.                                   0,         // yDst
  285.                                   cxDib,     // cxSrc
  286.                                   cyDib,     // cySrc
  287.                                   0,         // xSrc
  288.                                   0,         // ySrc
  289.                                   0,         // first scan line
  290.                                   cyDib,     // number of scan lines
  291.                                   pBits, 
  292.                                   pbmi, 
  293.                                   DIB_RGB_COLORS) ;
  294.           EndPaint (hwnd, &ps) ;
  295.           return 0 ;
  296.      
  297.      case WM_DESTROY:
  298.           if (pbmi)
  299.                free (pbmi) ;
  300.           
  301.           if (pBits)
  302.                free (pBits) ;
  303.  
  304.           PostQuitMessage (0) ;
  305.           return 0 ;
  306.      }
  307.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  308. }
  309.